<template>
  <div class="video-chat-container">
    <!-- 远程视频显示（主画面） -->
    <div class="remote-video-container">
      <video ref="remoteVideo" autoplay class="remote-video"></video>
      <div class="call-status" v-if="connectionStatus !== '已连接'">
        <div class="user-avatar">
          <div class="avatar-placeholder">{{ targetUserName }}</div>
        </div>
        <p class="status-text">等待对方接受邀请...</p>
      </div>
    </div>

    <!-- 本地视频预览（画中画） -->
    <div class="local-video-wrapper">
      <video ref="localVideo" autoplay muted class="local-video"></video>
    </div>

    <!-- 底部控制栏 -->
    <div class="control-bar">
      <div class="control-button" @click="toggleMic">
        <div class="button-icon" :class="{ 'button-active': micActive }">
          <svg v-if="micActive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
               fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
            <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
            <line x1="12" y1="19" x2="12" y2="23"></line>
            <line x1="8" y1="23" x2="16" y2="23"></line>
          </svg>
          <svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
               stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <line x1="1" y1="1" x2="23" y2="23"></line>
            <path d="M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6"></path>
            <path d="M17 16.95A7 7 0 0 1 5 12v-2m14 0v2a7 7 0 0 1-.11 1.23"></path>
            <line x1="12" y1="19" x2="12" y2="23"></line>
            <line x1="8" y1="23" x2="16" y2="23"></line>
          </svg>
        </div>
      </div>

      <div class="control-button" @click="toggleCamera">
        <div class="button-icon" :class="{ 'button-active': cameraActive }">
          <svg v-if="cameraActive" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
               fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path>
            <circle cx="12" cy="13" r="4"></circle>
          </svg>
          <svg v-else xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
               stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <line x1="1" y1="1" x2="23" y2="23"></line>
            <path d="M21 21H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3m3-3h6l2 3h4a2 2 0 0 1 2 2v9.34"></path>
            <circle cx="12" cy="13" r="4"></circle>
          </svg>
        </div>
      </div>

      <div class="end-call-button" @click="endCall">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <path
              d="M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91"></path>
          <line x1="23" y1="1" x2="1" y2="23"></line>
        </svg>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref, onMounted, onUnmounted, provide} from 'vue'
import {useRoute} from "vue-router";
import router from "@/router";
import {useCallStore} from "@/stores/call.ts";
import axios from 'axios';

// 统一使用ws作为WebSocket引用
const ws = ref<WebSocket | null>(null)
provide('websocket', ws)

interface SignalingMessage {
  type: 'offer' | 'answer' | 'candidate' | 'join' | 'leave' | 'invite' | 'invitation' | 'target_busy' | 'call_ended' | 'reject'
  roomId: string
  senderId: string
  data: any
}

declare global {
  interface Window {
    testNotify?: () => void
  }
}

// 视频元素引用
const localVideo = ref<HTMLVideoElement | null>(null)
const remoteVideo = ref<HTMLVideoElement | null>(null)

// WebRTC相关引用
const peerConnection = ref<RTCPeerConnection | null>(null)
const localStream = ref<MediaStream | null>(null)
const currentRoomId = ref('')
const route = useRoute()
const token = ref(localStorage.getItem('token'))
const userId = ref('-1')
const targetUserName = ref('被邀请')

// 控制状态
const micActive = ref(true)
const cameraActive = ref(true)
const connectionStatus = ref('未连接')
const iceStatus = ref('未开始')
const invitationTimeout = ref<NodeJS.Timeout | null>(null)

// 工具函数：从Token解析用户ID
const getUserIdFromToken = (token: string) => {
  if (!token) return '';
  try {
    const payloadBase64 = token.split('.')[1];
    const decoded = JSON.parse(atob(payloadBase64));
    return decoded.sub;
  } catch (error) {
    console.error('Token解析失败:', error);
    return '';
  }
};

// 安全WebSocket操作封装
const safeWebSocketOperation = (operation: (socket: WebSocket) => void) => {
  if (ws.value && ws.value.readyState === WebSocket.OPEN) {
    operation(ws.value)
  } else {
    console.warn('WebSocket不可用，当前状态:', ws.value?.readyState)
  }
}

const props = withDefaults(defineProps<{
  targetUserId: string | null;  // 被邀请的用户id
}>(), {
  targetUserId: null
});

onMounted(async () => {
  userId.value = getUserIdFromToken(token.value);
  console.log('用户ID：', userId.value)

  currentUserId.value = userId.value;

  axios.get('http://192.168.1.17:8020/user/GetUserInfo', {
    params: {
      userId: props.targetUserId,
    }
  }).then(res => {
    // 验证接口返回结构是否正确
    console.log('用户数据加载成功：', res.data);
    targetUserName.value = res.data.username;
  })

  try {
    // 获取用户媒体设备
    localStream.value = await navigator.mediaDevices.getUserMedia({
      audio: true,
      video: true
    })

    if (localVideo.value && localStream.value) {
      localVideo.value.srcObject = localStream.value
    }

    const randomRoomId = 'room' + Math.floor(10000 + Math.random() * 90000);
    currentRoomId.value = randomRoomId;

    if (route.query.role === 'caller') {
      await setupSignaling(randomRoomId)
      console.log('11111111111111111111')

      await initPeerConnection()
      console.log('2222222222222')

      await sendInvitation({
        targetUserId: route.query.targetUserId as string,
        roomId: randomRoomId,
        role: 'caller',
      });

      await startCall()
      console.log('开始通话')
    } else if (route.query.role === 'receiver') {
      await setupSignaling(route.query.roomId as string)
      console.log('3333333333333333')

      await initPeerConnection()
      console.log('4444444444444444')

      await startCall()
      console.log('开始通话')
    }
  } catch (error) {
    const err = error as Error;
    console.error('初始化失败:', err);
    connectionStatus.value = '初始化失败: ' + err.message;
  }
})

onUnmounted(() => {
  if (invitationTimeout.value) {
    clearTimeout(invitationTimeout.value)
  }
  console.log('通话结束，清空超时计时器');
  endCall()
})

/**
 * 发送视频通话邀请
 */
const sendInvitation = async (params: {
  targetUserId: string;
  roomId: string;
  role: 'caller';
}) => {
  try {
    safeWebSocketOperation((socket) => {
      socket.send(JSON.stringify({
        type: 'invite',
        roomId: params.roomId,
        senderId: currentUserId.value,
        data: {
          targetUserId: params.targetUserId,
          callType: 'video',
          timestamp: Date.now()
        }
      }))
    })

    console.log('邀请已发送至用户:', params.targetUserId);

    // 超时监控
    invitationTimeout.value = setTimeout(() => {
      console.warn('邀请超时未响应');
      endCall();
      invitationTimeout.value = null;
    }, 30000);

    // 连接成功自动清除
    if (peerConnection.value) {
      peerConnection.value.oniceconnectionstatechange = () => {
        if (peerConnection.value?.iceConnectionState === 'connected' && invitationTimeout.value) {
          clearTimeout(invitationTimeout.value)
          invitationTimeout.value = null
          console.log('通话已连接，清空超时计时器')
        }
      }
    }
  } catch (error) {
    if (invitationTimeout.value) {
      clearTimeout(invitationTimeout.value)
      invitationTimeout.value = null
    }
    console.error('发送邀请失败:', error)
    connectionStatus.value = '邀请发送失败'
  }
}

/**
 * 初始化WebRTC连接
 */
const initPeerConnection = () => {
  const configuration = {
    iceServers: [
      {urls: 'stun:stun.voxgratia.org'},  // STUN服务器地址
    ]
  }

  peerConnection.value = new RTCPeerConnection(configuration)

  peerConnection.value.onicecandidate = (event) => {
    if (event.candidate) {
      sendCandidateToServer(event.candidate)
    }
  }

  peerConnection.value.ontrack = (event) => {
    console.log('收到远程流:', event.streams)
    connectionStatus.value = '已连接'
    if (remoteVideo.value && event.streams[0]) {
      remoteVideo.value.srcObject = event.streams[0]
    }
  }

  peerConnection.value.oniceconnectionstatechange = () => {
    if (peerConnection.value) {
      console.log('ICE连接状态:', peerConnection.value.iceConnectionState)
      iceStatus.value = peerConnection.value.iceConnectionState
    }
  }

  peerConnection.value.oniceconnectionstatechange = () => {
    if (peerConnection.value?.iceConnectionState === 'failed') {
      restartIce()
    }
  }

  if (localStream.value) {
    localStream.value.getTracks().forEach(track => {
      peerConnection.value?.addTrack(track, localStream.value!)
    })
  }
}

const restartIce = async () => {
  console.log("ICE协商失败，尝试重启...")
  try {
    if (!peerConnection.value) return

    const offer = await peerConnection.value.createOffer({ iceRestart: true })
    await peerConnection.value.setLocalDescription(offer)
    sendOfferToServer(offer)
  } catch (e) {
    console.error("ICE重启失败:", e)
  }
}

/**
 * 开始通话
 */
const startCall = async () => {
  if (!peerConnection.value) initPeerConnection()

  try {
    if (!peerConnection.value) return

    const offer = await peerConnection.value.createOffer()
    await peerConnection.value.setLocalDescription(offer)
    sendOfferToServer(offer)
  } catch (error) {
    console.error('创建Offer失败:', error)
  }
}

/**
 * 结束通话
 */
const endCall = async () => {
  console.group('开始结束通话流程')

  // 发送结束通知
  try {
    await sendToServer({
      type: 'call_ended',
      roomId: currentRoomId.value,
      senderId: userId.value,
      data: {
        force: true,
        timestamp: Date.now()
      }
    })
  } catch (e) {
    console.warn('结束通知发送失败（可能连接已断）:', e)
  }

  // 清理所有资源
  await cleanupResources()

  // 重置所有状态
  connectionStatus.value = '已挂断'
  iceStatus.value = '未开始'
  currentRoomId.value = 'default_room'
  callStore.callStatus = 'idle'

  console.groupEnd()

  // 跳转首页
  router.push('/').then(() => {
    window.location.reload() // 强制刷新页面
  })
}

/**
 * 初始化默认连接
 */
const initDefaultConnection = async () => {
  if (!userId.value || userId.value === '-1') {
    console.warn('无效用户ID，取消连接')
    return
  }

  // 状态重置
  callStore.callStatus = 'idle'
  currentRoomId.value = 'default_room'

  // 关闭旧连接
  await new Promise<void>((resolve) => {
    if (!ws.value || ws.value.readyState === WebSocket.CLOSED) {
      return resolve()
    }

    // 解除所有事件监听
    ws.value.onmessage = null
    ws.value.onerror = null
    ws.value.onopen = null

    const onCloseHandler = () => {
      console.log('旧连接完全释放')
      ws.value!.onclose = null
      resolve()
    }

    ws.value.onclose = onCloseHandler
    ws.value.close()
  })

  // 延迟资源释放
  await new Promise(resolve => setTimeout(resolve, 500))

  // 建立新连接
  const newWs = new WebSocket(
      `ws://192.168.1.17:8010/signaling?userId=${userId.value}&roomId=default_room&purpose=reconnect&timestamp=${Date.now()}`
  )

  // 消息处理
  newWs.onmessage = (event) => {
    try {
      const message = JSON.parse(event.data) as {
        type: string
        data?: any
      }

      if (message.type === 'connection_verified') {
        console.log('连接验证通过:', message.data)
        callStore.callStatus = 'idle'
      }
    } catch (e) {
      console.error('消息解析失败:', e)
    }
  }

  newWs.onopen = () => {
    console.log('物理连接已建立')
    newWs.send(JSON.stringify({
      type: 'join',
      roomId: 'default_room',
      senderId: userId.value,
      data: {
        isDefault: true,
        reconnect: true,
        version: '1.0'
      }
    }))
  }

  newWs.onerror = (e) => {
    console.error('连接错误:', e)
    setTimeout(initDefaultConnection, 2000 + Math.random() * 3000)
  }

  newWs.onclose = (e) => {
    if (!e.wasClean) {
      console.warn('连接异常关闭:', e.code, e.reason)
      setTimeout(initDefaultConnection, 1000)
    }
  }

  ws.value = newWs
}

const cleanupResources = async () => {
  console.log('🧹 开始清理资源')

  // 清除超时计时器
  if (invitationTimeout.value) {
    clearTimeout(invitationTimeout.value)
    invitationTimeout.value = null
  }

  // 停止所有媒体轨道
  if (localStream.value) {
    localStream.value.getTracks().forEach(track => {
      track.stop()
      track.enabled = false
    })
    localStream.value = null
  }

  // 关闭PeerConnection
  if (peerConnection.value) {
    peerConnection.value.close()
    peerConnection.value = null
  }

  // 清除视频源
  if (localVideo.value) localVideo.value.srcObject = null
  if (remoteVideo.value) remoteVideo.value.srcObject = null

  // 添加延迟确保资源释放
  await new Promise(resolve => setTimeout(resolve, 300))

  console.log('资源清理完成')
}

/**
 * 切换麦克风状态
 */
const toggleMic = () => {
  if (localStream.value) {
    const audioTracks = localStream.value.getAudioTracks()
    if (audioTracks.length > 0) {
      audioTracks[0].enabled = !audioTracks[0].enabled
      micActive.value = audioTracks[0].enabled
    }
  }
}

/**
 * 切换摄像头状态
 */
const toggleCamera = () => {
  if (localStream.value) {
    const videoTracks = localStream.value.getVideoTracks()
    if (videoTracks.length > 0) {
      videoTracks[0].enabled = !videoTracks[0].enabled
      cameraActive.value = videoTracks[0].enabled
    }
  }
}

const signalingSocket = ref<WebSocket | null>(null)
const currentUserId = ref('-1')
const SIGNALING_SERVER = 'ws://192.168.1.17:8010/signaling'
const callStore = useCallStore()

/**
 * 初始化信令连接
 */
const setupSignaling = (roomId: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    currentRoomId.value = roomId
    callStore.callStatus = 'in_call'
    console.log('救命' + callStore.callStatus)

    signalingSocket.value = new WebSocket(`${SIGNALING_SERVER}?roomId=${roomId}&userId=${currentUserId.value}`)

    const originalOnOpen = () => {
      console.log('信令连接已建立')
      safeWebSocketOperation((socket) => {
        socket.send(JSON.stringify({
          type: 'join',
          roomId,
          senderId: currentUserId.value,
          data: null
        }))
      })
      resolve()
    }

    ws.value = signalingSocket.value

    ws.value.onopen = originalOnOpen

    ws.value.onerror = (error) => {
      const errMsg = `信令连接失败: ${error instanceof Error ? error.message : '未知错误'}`
      console.error(errMsg)
      reject(new Error(errMsg))
      signalingSocket.value?.close()
    }

    ws.value.onmessage = async (event) => {
      try {
        const message = JSON.parse(event.data) as SignalingMessage;

        if (message.type === 'call_ended') {
          console.log('收到通话结束通知', message);
          callStore.callStatus = 'idle'
          console.log('啊啊啊' + callStore.callStatus)
          endCall()
          if (invitationTimeout.value) {
            clearTimeout(invitationTimeout.value)
            invitationTimeout.value = null
          }
          console.log('通话已连接，清空超时计时器')

          if (peerConnection.value) peerConnection.value.close()
          if (localStream.value) {
            localStream.value.getTracks().forEach(track => track.stop())
          }

          connectionStatus.value = '对方已挂断'
          iceStatus.value = '已结束'

          setTimeout(() => {
            router.push('/')
          }, 3000)

          return
        }

        await handleSignalingMessage(message)
      } catch (error) {
        console.error('消息解析失败', error)
      }
    }

    ws.value.onclose = () => {
      console.log('信令连接已关闭')
      if (peerConnection.value?.iceConnectionState !== 'closed') {
        setTimeout(() => setupSignaling(roomId), 3000)
      }
    }

    const timeout = setTimeout(() => {
      reject(new Error('信令连接超时'))
      ws.value?.close()
    }, 5000)

    ws.value.onopen = () => {
      clearTimeout(timeout)
      originalOnOpen()
    }
  })
}

/**
 * 处理信令消息
 */
const handleSignalingMessage = async (message: SignalingMessage) => {
  console.log("收到信令:", message.type)

  if (message.type === 'target_busy'){
    safeWebSocketOperation((socket) => {
      socket.send(JSON.stringify({
        type: 'leave',
        roomId: currentRoomId.value,
        senderId: currentUserId.value,
        data: { reason: 'normal_hangup' }
      }))
    })
    router.go(-1)
    return
  }

  switch (message.type) {
    case 'offer':
      if (message.data?.sdp) {
        await handleRemoteOffer(message.data)
      } else {
        console.error("无效的offer消息", message)
      }
      break

    case 'answer':
      if (message.data?.sdp) {
        await handleRemoteAnswer(message.data)
      }
      break

    case 'candidate':
      try {
        const iceCandidate = new RTCIceCandidate({
          candidate: message.data.candidate,
          sdpMid: message.data.sdpMid,
          sdpMLineIndex: message.data.sdpMLineIndex
        })
        await peerConnection.value?.addIceCandidate(iceCandidate)
      } catch (e) {
        console.error("添加候选失败:", e)
      }
      break

    case 'reject':
      console.log('收到拒绝通知', message)
      router.go(-1)
      break
  }
}

const handleRemoteOffer = async (offerData: any) => {
  if (!offerData?.sdp || !offerData?.type) {
    console.error("无效的Offer格式", offerData)
    return
  }

  if (!peerConnection.value) return

  await peerConnection.value.setRemoteDescription({
    type: offerData.type,
    sdp: offerData.sdp
  })
  const answer = await peerConnection.value.createAnswer()
  await peerConnection.value.setLocalDescription(answer)
  sendAnswerToServer(answer)
}

const handleRemoteAnswer = async (answerData: any) => {
  if (!answerData?.sdp || !answerData?.type) {
    console.error("无效的Answer格式", answerData)
    return
  }

  if (!peerConnection.value) return

  await peerConnection.value.setRemoteDescription({
    type: answerData.type,
    sdp: answerData.sdp
  })
}

/**
 * 发送消息到服务器
 */
const sendToServer = (message: SignalingMessage) => {
  safeWebSocketOperation((socket) => {
    socket.send(JSON.stringify(message))
  })
}

/**
 * 发送ICE候选
 */
const sendCandidateToServer = (candidate: RTCIceCandidate) => {
  sendToServer({
    type: 'candidate',
    roomId: currentRoomId.value,
    senderId: currentUserId.value,
    data: {
      candidate: candidate.candidate,
      sdpMid: candidate.sdpMid,
      sdpMLineIndex: candidate.sdpMLineIndex,
      usernameFragment: candidate.usernameFragment
    }
  })
}

/**
 * 发送Offer
 */
const sendOfferToServer = (offer: RTCSessionDescriptionInit) => {
  sendToServer({
    type: 'offer',
    roomId: currentRoomId.value,
    senderId: currentUserId.value,
    data: offer
  })
}

/**
 * 发送Answer
 */
const sendAnswerToServer = (answer: RTCSessionDescriptionInit) => {
  sendToServer({
    type: 'answer',
    roomId: currentRoomId.value,
    senderId: currentUserId.value,
    data: answer
  })
}
</script>

<style scoped>
/* 基础样式 */
.video-chat-container {
  position: relative;
  width: 100%;
  height: 100vh;
  background: #1a1a2e;
  overflow: hidden;
  font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
  color: white;
}

/* 远程视频容器 */
.remote-video-container {
  width: 100%;
  height: 100%;
  background: #16213e;
  position: relative;
}

.remote-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 呼叫状态显示 */
.call-status {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.5);
  z-index: 10;
}

.user-avatar {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background: #4a4e69;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px;
}

.avatar-placeholder {
  font-size: 36px;
  color: #f8f9fa;
}

.status-text {
  font-size: 18px;
  color: #f8f9fa;
  margin-top: 16px;
}

/* 本地视频预览 */
.local-video-wrapper {
  position: absolute;
  right: 20px;
  top: 30px;
  width: 100px;
  height: 140px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  z-index: 20;
}

.local-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 底部控制栏 */
.control-bar {
  position: absolute;
  bottom: 40px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 40px;
  z-index: 30;
}

.control-button {
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
}

.button-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

.button-icon svg {
  color: white;
  width: 24px;
  height: 24px;
}

.button-active {
  background: rgba(255, 255, 255, 0.2);
}

.button-label {
  margin-top: 8px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
}

.end-call-button {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: #ff5c5c;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(255, 92, 92, 0.3);
  transition: all 0.3s ease;
}

.end-call-button:hover {
  background: #ff3b3b;
  transform: scale(1.05);
}

.end-call-button svg {
  color: white;
  width: 24px;
  height: 24px;
}
</style>